#ifndef ARMOR_H
#define ARMOR_H

#include <opencv2/opencv.hpp>


class Armor {
 public:
    enum class Color : int { ERROR=-1, GRAY = 0, RED = 1, BLUE = 2 };
    struct Lightbar {
        cv::RotatedRect rect;
        cv::RotatedRect elli_rect;
        double rate{0.0};
        double angle{0.0};
        Color color{};
        static bool coordinateComparator(const Lightbar &a, const Lightbar &b)
        {
            if (a.rect.center.x == b.rect.center.x) { return (a.rect.center.y < b.rect.center.y); }
            else { return (a.rect.center.x < b.rect.center.x); }
        }
    };

 public:
   
    /// 装甲板颜色
    Color armor_color;

    /// 装甲板数字编号的图像
    cv::Mat number_img;

    /// 输入的矩形
    cv::Rect roi_rect;

    ///自适应曝光灰度图
    cv::Mat exposure_gray;

    /// 贴合装甲板区域的旋转矩形
    cv::RotatedRect armor_rect;
    // 左灯条矩形
    cv::RotatedRect lbar_rect;
    // 右灯条矩形
    cv::RotatedRect rbar_rect;

    /// 分类器推理的装甲板数字编号
    int classifier_num{};


    /// 距离误差分数
    double distance = 0.0;

    /// 装甲板误差分数
    double ratio = 0.0;

    /// 两灯条高度比例误差分数
    double bar_len_ratio = 0.0;

    /// 两灯条倾斜度之差误差分数
    double bar_delta_angle = 0.0;


    // 装甲板倾斜程度误差分数
    double armor_angle = 0.0;

 private:
    /// 旋转矩形宽度放大倍率, 尽可能保证截取数字区域的全部特征
    constexpr static double ROTATEDRECT_WIDTH_RATE = 1.0;

    /// 旋转矩形高度放大倍率, 尽可能保证截取数字区域的全部特征
    constexpr static double ROTATEDRECT_HEIGHT_RATE = 2.0;

 public:
    /**
     * @brief 默认构造函数
     */
    Armor();

    /**
     * @brief 默认析构函数
     */
    ~Armor();

    /**
     * @brief 根据左右灯条给armor类成员赋值
     */
    void assignMemberVariables(const Lightbar &lbar, const Lightbar &rbar);

    /// 根据四个点给armor类成员赋值
    void assignMemberVariables(const std::array<cv::Point2f, 4>& coordinates);

    void setNumberImg(const cv::Mat& img);

    [[nodiscard]] inline cv::Rect rect() const
    { return armor_rect.boundingRect(); }

    [[nodiscard]] inline bool isBigArmor() const
    { return ratio > 3.4; }

    /**
     * @brief 获取装甲板数字编号
     *
     * @return 装甲板数字编号(常量）
     */
    [[nodiscard]] inline int getNumber() const
    { return classifier_num; }

    /**
     * @brief 防止截取的数字区域超出图像区域
     */
    static void preventExceed(int &x, int &y, int &width, int &height, const cv::Mat &src);

    /**
    * @brief 将装甲板那的一些信息打印到终端上 
    */
    void listInfo() const;

 private:
    static void extractPoints(const cv::RotatedRect &rect, std::vector<cv::Point> &points);
};

#endif// ARMOR_H
